#include <iostream>
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <X11/extensions/XTest.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <cstring>

#include <vector>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <functional>

#include <csignal>
#include <future>
#include <arpa/inet.h>
#include <fcntl.h>
#include <pthread.h>

#include "IniFileParser.h"

// #include "remote_control.h"

class ThreadPool
{
private:
    std::vector<std::thread> workers;
    std::queue<std::function<void()>> tasks;

    std::mutex queue_mutex;
    std::condition_variable condition;
    bool stop = false;

public:
    ThreadPool(size_t threads) : stop(false)
    {
        for (size_t i = 0; i < threads; ++i)
        {
            workers.emplace_back(
                [this]
                {
                    while (true)
                    {
                        std::function<void()> task;

                        {
                            std::unique_lock<std::mutex> lock(this->queue_mutex);
                            this->condition.wait(lock,
                                                 [this]
                                                 { return this->stop || !this->tasks.empty(); });

                            if (this->stop && this->tasks.empty())
                            {
                                return;
                            }
                            task = std::move(this->tasks.front());
                            this->tasks.pop();
                        }

                        task();
                    }
                });
        }
    }

    ~ThreadPool()
    {
        {
            std::unique_lock<std::mutex> lock(queue_mutex);
            stop = true;
        }
        condition.notify_all();

        for (std::thread &worker : workers)
        {
            worker.join();
        }
    }

    template <class F, class... Args>
    auto enqueue(F &&f, Args &&...args)
        -> std::future<typename std::result_of<F(Args...)>::type>
    {

        using return_type = typename std::result_of<F(Args...)>::type;

        auto task = std::make_shared<std::packaged_task<return_type()>>(
            std::bind(std::forward<F>(f), std::forward<Args>(args)...));

        std::future<return_type> res = task->get_future();
        {
            std::unique_lock<std::mutex> lock(queue_mutex);

            // The lambda function captures 'shared_ptr<task>' by value
            // so that it stays alive until the task is executed
            tasks.emplace([task]()
                          { (*task)(); });
        }
        condition.notify_one();
        return res;
    }
};

// 信号处理的全局标志
volatile sig_atomic_t shutdown_requested = 0;

// 信号处理函数
void signal_handler(int signum)
{
    std::cout << "捕获到信号 " << signum << std::endl;
    shutdown_requested = 1;
}

struct CaptureEventHandler
{
    Display *display;
    int sock;
};

void simulateKeyPress(Display *display, KeySym key, bool press)
{
    std::cout << "Received event: (" << key << ", " << press << ")" << std::endl;
    if (press)
    {
        XTestFakeKeyEvent(display, XKeysymToKeycode(display, key), True, CurrentTime);
        // XTestFakeKeyEvent(display, XKeysymToKeycode(display, key), False, CurrentTime);
    }
    else
    {
        XTestFakeKeyEvent(display, XKeysymToKeycode(display, key), False, CurrentTime);
    }
    XFlush(display);
}

void simulateMouseClick(Display *display, int button, int x, int y, bool press)
{
    std::cout << "Received event: (" << button << ", " << x << ", " << y << ", " << press << ")" << std::endl;

    XTestFakeMotionEvent(display, DefaultScreen(display), x, y, CurrentTime);
    XFlush(display);

    if (press)
    {
        XTestFakeButtonEvent(display, button, True, CurrentTime);
        // XTestFakeButtonEvent(display, button, False, CurrentTime);
    }
    else
    {
        XTestFakeButtonEvent(display, button, False, CurrentTime);
    }
    XFlush(display);
}

void simulateMouseMotion(Display *display, int x, int y)
{
    std::cout << "Received event: (" << x << ", " << y << ")" << std::endl;

    XTestFakeMotionEvent(display, DefaultScreen(display), x, y, CurrentTime+2);

    XFlush(display);
}
void simulateCommandExec(char *cmd)
{
    system(cmd);
}
void *handleClient(void *arg)
{
    if (arg != NULL)
    {
        CaptureEventHandler *ceh = (CaptureEventHandler *)arg;
        Display *display = ceh->display; // 不了解Display原理,此处不保证display线程安全,待进一步了解
        int sock = ceh->sock;

        XEvent event;
        ssize_t bytes_read;

        while ((bytes_read = recv(sock, &event, sizeof(event), 0)) > 0)
        {
            if (bytes_read != sizeof(event))
            {
                std::cerr << "Incomplete event received" << std::endl;
                break;
            }
            // 处理事件
            switch (event.type)
            {
            case KeyPress:
            case KeyRelease:
                simulateKeyPress(display, XLookupKeysym(&event.xkey, 0), KeyPress == event.type ? True : False);
                break;
            case ButtonPress:
            case ButtonRelease:
                simulateMouseClick(display, event.xbutton.button, event.xbutton.x, event.xbutton.y, KeyPress == event.type ? True : False);
                break;
            case MotionNotify:
                simulateMouseMotion(display, event.xmotion.x, event.xmotion.y);
            default:
                std::cerr << "Unknown event type" << std::endl;
            }
        }

        close(sock);
    }
    return NULL;
}

// 将套接字设置为非阻塞模式
int setNonBlocking(int fd)
{
    int flags;

    // 获取当前的文件状态标志
    if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
    {
        perror("fcntl");
        return -1;
    }

    // 设置非阻塞标志
    flags |= O_NONBLOCK;

    // 更新文件状态标志
    if (fcntl(fd, F_SETFL, flags) == -1)
    {
        perror("fcntl");
        return -1;
    }

    return 0;
}
int main()
{
    int server_sock, client_sock;
    struct sockaddr_in server_addr, client_addr;
    socklen_t sin_size = sizeof(struct sockaddr_in);
    CaptureEventHandler ceh;

    signal(SIGINT, signal_handler); // 注册信号处理函数

    // IniFileParser ini_parser("../config.ini");
    std::shared_ptr<IniFileParser> iniParserPtr = std::make_shared<IniFileParser>("../config.ini");

    int port;
    uint16_t usPort;
    if (!iniParserPtr->getIntValue("port", port))
    {
        return EXIT_FAILURE;
    }
    if (port < 0 || port > std::numeric_limits<uint16_t>::max())
    {
        std::cerr << "Invalid port number " << port << std::endl;
        return EXIT_FAILURE;
    }
    else if (port > 0 && port < 1024) // 知名端口，通常被IANA（互联网号码分配机构）分配给一些公认的服务
    {
        std::cerr << "port number " << port << " is not available." << std::endl;
        return EXIT_FAILURE;
    }
    else
    {
        usPort = static_cast<uint16_t>(port);
    }

    // 初始化X11显示
    Display *display;
    Window root_window;
    display = XOpenDisplay(NULL);
    if (display == NULL)
    {
        std::cerr << "Cannot open display" << std::endl;
        return EXIT_FAILURE;
    }
    root_window = DefaultRootWindow(display);
    ceh.display = display;

    // 创建并绑定套接字
    server_sock = socket(AF_INET, SOCK_STREAM, 0);
    if (server_sock < 0)
    {
        std::cerr << "Cannot create socket" << std::endl;
        XCloseDisplay(display);
        return EXIT_FAILURE;
    }

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(usPort); // 假设的端口号

    if (bind(server_sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) < 0)
    {
        std::cerr << "Bind failed" << std::endl;
        close(server_sock);
        XCloseDisplay(display);
        return EXIT_FAILURE;
    }

    if (listen(server_sock, 5) < 0)
    { // 监听，最大连接数设为5
        std::cerr << "Listen failed" << std::endl;
        close(server_sock);
        XCloseDisplay(display);
        return EXIT_FAILURE;
    }
    // 设置套接字为非阻塞模式
    if (setNonBlocking(server_sock) < 0)
    {
        perror("setNonBlocking failed");
        close(server_sock);
        return EXIT_FAILURE;
    }
    std::cout << "Server is listening on port 12345..." << std::endl;
    ThreadPool pool(1); // 创建一个有4个线程的线程池
    while (0 == shutdown_requested)
    {
        if ((client_sock = accept(server_sock, (struct sockaddr *)&client_addr, &sin_size)) < 0)
        {
            // 检查是否是EAGAIN或EWOULDBLOCK，表示没有连接到来
            if (errno == EAGAIN || errno == EWOULDBLOCK)
            {
                // std::cout << "No connections, polling..." << std::endl;
                std::this_thread::sleep_for(std::chrono::milliseconds(10));
                continue;
            }
        }

        // std::cout << "Accepted new connection from " << inet_ntoa(client_addr.sin_addr) << std::endl;
        ceh.sock = client_sock;

        pool.enqueue(handleClient, (void *)&ceh);
    }
    // 关闭套接字和X11显示
    close(server_sock);
    XCloseDisplay(display);
    return EXIT_SUCCESS;
}
